package com.lims.filter;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import com.lims.common.Conts;
import com.lims.common.ResultCode;
import com.lims.exception.BaseException;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.util.ContentCachingRequestWrapper;

import java.util.List;


@Slf4j
@Component
public class ReqFilter extends OncePerRequestFilter {
    /**
     * 白名单列表，例如文件类请求不打印入参
     */
    private static final List<String> WHITE_URL = List.of(
            "/lims/test/test/check");

    @Resource
    private HandlerExceptionResolver handlerExceptionResolver;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
        try {
            String traceId =request.getHeader(Conts.TRACE_ID);
            if (StrUtil.isBlank(traceId)) {
                traceId = RandomUtil.randomString(16);
            }
            MDC.put(Conts.TRACE_ID, traceId);
            if(WHITE_URL.contains(request.getRequestURI())){
                filterChain.doFilter(request, response);
                return;
            }
            //禁用处post外的所有请求
            if(!RequestMethod.POST.name().equals(request.getMethod())){
                throw new BaseException(ResultCode.POST_ERROR);
            }
            //禁用处application/json格式外的所有请求
            if(StrUtil.isBlank(request.getContentType()) ){
                throw new BaseException(ResultCode.CONTENT_TYPE_ERROR);
            }
            if(!request.getContentType().contains(ContentType.JSON.getValue())){
                throw new BaseException(ResultCode.JSON_ERROR);
            }
            //使用可多次读取请求体的对象，用于统一异常拦截获取请求体
            ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
            filterChain.doFilter(wrappedRequest, response);
        } catch (Exception e) {
            //交给全局异常处理类处理
            handlerExceptionResolver.resolveException(request, response, null, e);
        }finally {
            MDC.remove(Conts.TRACE_ID);
        }
    }
}
